#ifndef YHAIDA_THREADLOCALSINGLETON_H
#define YHAIDA_THREADLOCALSINGLETON_H
#include "../base/Utils.h"
#include <assert.h>
#include <pthread.h>
namespace yhaida
{
    template <typename T>
    class ThreadLocalSingleton : Utils::nocapyable
    {
    public:
        ThreadLocalSingleton() = delete;
        ~ThreadLocalSingleton() = delete;

        static T &instance()
        {
            if (!_value)
            {
                _value = new T();
                _deleter.set(_value);
            }
            return *_value;
        }

        static T *pointer()
        {
            return _value;
        }

    private:
        static void destructor(void *obj)
        {
            //在调用析构函数的时候先要判断pthread_key_t对应的内存的值是不是t_value_对应的那块。
            //如果是的话就继续，不是的话就报错了！！
            assert(obj == _value);
            //检查类型完整性
            typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
            T_must_be_complete_type dummy;
            (void)dummy;

            delete _value;
            _value = nullptr;
        }

    private:
        class Deleter //单例模式无法调用析构函数，Deleter类来充当析构函数的作用
        {
        public:
            Deleter()
            {
                pthread_key_create(&_pkey, &ThreadLocalSingleton::destructor);
            }
            ~Deleter()
            {
                pthread_key_delete(_pkey);
            }

            void set(T *newOne)
            {
                // int pthread_setspecific(pthread_key_t key, const void *value);存
                // void *pthread_getspecific(pthread_key_t key);取

                assert(pthread_getspecific(_pkey) == NULL);
                pthread_setspecific(_pkey, newOne);
            }

        private:
            pthread_key_t _pkey;
        };

    private:
        static __thread T *_value;
        static Deleter _deleter;
    };
    template <typename T>
    __thread T *ThreadLocalSingleton<T>::_value = 0;

    template <typename T>
    typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::_deleter;

}

#endif